package com.example.java_gobang.game;

import com.example.java_gobang.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import javax.imageio.IIOException;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

// 匹配器
// 负责完成整个匹配功能
@Component
public class Matcher {
    // 根据天梯积分分为大致的三个队列
    private Queue<User> normalQueue = new LinkedList<>();
    private Queue<User> highQueue = new LinkedList<>();
    private Queue<User> veryHighQueue = new LinkedList<>();

    @Autowired
    private OnlineUserManger onlineUserManger;

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private RoomManager roomManager;

    // 把玩家放到匹配队列中
    public void add(User user){
        if(user.getScore() < 2000){
            synchronized (normalQueue){
                normalQueue.offer(user);
                normalQueue.notify();
            }
            System.out.println("把玩家 " + user.getUsername() + " 加入了 normalQueue");
        } else if (user.getScore() < 3000) {
            synchronized (highQueue){
                highQueue.offer(user);
                highQueue.notify();
            }
            System.out.println("把玩家 " + user.getUsername() + " 加入了 highQueue");
        } else{
            synchronized (veryHighQueue){
                veryHighQueue.offer(user);
                veryHighQueue.notify();
            }
            System.out.println("把玩家 " + user.getUsername() + " 加入了 veryHighQueue");
        }

    }

    // 把玩家移除匹配队列
    public void remove(User user){
        if(user.getScore() < 2000){
            synchronized (normalQueue){
                normalQueue.remove(user);
            }
            System.out.println("把玩家 " + user.getUsername() + " 移除了 normalQueue");
        } else if (user.getScore() < 3000) {
            synchronized (highQueue){
                highQueue.remove(user);
            }
            System.out.println("把玩家 " + user.getUsername() + " 移除了 highQueue");
        } else{
            synchronized (veryHighQueue){
                veryHighQueue.remove(user);
            }
            System.out.println("把玩家 " + user.getUsername() + " 移除了 veryHighQueue");
        }
    }

    public Matcher(){
        // 创建三个线程，分别针对这三个匹配队列
        Thread t1 = new Thread(){
            @Override
            public void run() {
                // 扫描 normalQueue
                while (true){
                    handlerMatch(normalQueue);
                }
            }
        };
        t1.start();

        Thread t2 = new Thread(){
            @Override
            public void run() {
                while (true){
                    handlerMatch(highQueue);
                }
            }
        };
        t2.start();

        Thread t3 = new Thread(){
            @Override
            public void run() {
                while (true){
                    handlerMatch(veryHighQueue);
                }
            }
        };
        t3.start();

    }
    private void handlerMatch(Queue<User> matchQueue) throws RuntimeException {
        synchronized (matchQueue){
            try {
                // 检测队列中是否有两个玩家
                // 仅添加一个元素不可以被唤醒，不使用 if
                while (matchQueue.size() < 2){
                    matchQueue.wait();
                }
                // 取出两个玩家
                User player1 = matchQueue.poll();
                User player2 = matchQueue.poll();
                System.out.println("匹配出两个玩家: " + player1.getUsername() + ", " + player2.getUsername());
                // 获取玩家的 websocket 会话，告知玩家匹配成功
                WebSocketSession session1 = onlineUserManger.getFromGameHall(player1.getUserId());
                WebSocketSession session2 = onlineUserManger.getFromGameHall(player2.getUserId());

                //当有一方断开连接，就继续将另一方放回匹配队列中
                if(session1 == null){
                    matchQueue.offer(player2);
                    return;
                }
                if(session2 == null){
                    matchQueue.offer(player1);
                    return;
                }
                // 两个玩家是同一个用户
                if(session1 == session2){
                    // 把其中一个放回匹配队列
                    matchQueue.offer(player1);
                    return;
                }

                // 把两个玩家放到同一个游戏房间
                Room room = new Room();
                roomManager.add(room,player1.getUserId(), player2.getUserId());

                // 给玩家反馈信息 —— 匹配成功
                MatchResponse response1 = new MatchResponse();
                response1.setOk(true);
                response1.setMessage("matchSuccess");
                String json1 = objectMapper.writeValueAsString(response1);
                session1.sendMessage(new TextMessage(json1));

                MatchResponse response2 = new MatchResponse();
                response2.setOk(true);
                response2.setMessage("matchSuccess");
                String json2 = objectMapper.writeValueAsString(response2);
                session2.sendMessage(new TextMessage(json2));
            }catch (IOException e){
                e.printStackTrace();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
